﻿#ifndef __LUA_FUNCTION_REGISTRATION_H__
#define __LUA_FUNCTION_REGISTRATION_H__

#include "./luafunction.h"
#include "./luaregistration.h"

template <class F>
class FunctionRegistration : public Registration
{
public:
    FunctionRegistration(const char * name, F func) :
        m_name(name),
        m_func(func)
    {
    }
protected:
    const char * m_name;
    const F m_func;
};

template <class F>
class NormalFunctionRegistration : public FunctionRegistration<F>
{
public:
    NormalFunctionRegistration(const char * name, F func) :
        FunctionRegistration<F>(name, func)
    {
    }
    void Register(lua_State* luaState, bool bGlobal) const
    {       
        if (bGlobal)
        {
            LuaFunction<F>::BindFunc(luaState, m_func);
            lua_setglobal(luaState, m_name);
        }
        else
        {
            lua_pushstring(luaState, m_name);
            LuaFunction<F>::BindFunc(luaState, m_func);
            lua_settable(luaState, -3);
        }

        Registration::Register(luaState, bGlobal);
    }
};

template <class F>
class WrapperFunctionRegistration : public FunctionRegistration<F>
{
public:
    WrapperFunctionRegistration(const char * name, F func) :
        FunctionRegistration<F>(name, func)
    {
    }
    void Register(lua_State* luaState, bool bGlobal) const
    {       
        if (bGlobal)
        {
            LuaWrapperFunction<F>::BindFunc(luaState, m_func);
            lua_setglobal(luaState, m_name);
        }
        else
        {
            lua_pushstring(luaState, m_name);
            LuaWrapperFunction<F>::BindFunc(luaState, m_func);
            lua_settable(luaState, -3);
        }

        Registration::Register(luaState, bGlobal);
    }
};

template <class F>
class GetFunctionRegistration : public FunctionRegistration<F>
{
public:
    GetFunctionRegistration(const char * name, F func) :
        FunctionRegistration<F>(name, func)
    {
    }
    void Register(lua_State* luaState, bool bGlobal) const
    {       
        if (bGlobal)
        {
            LuaGetFunction<F>::BindFunc(luaState, m_func);
            lua_setglobal(luaState, m_name);
        }
        else
        {
            lua_pushstring(luaState, m_name);
            LuaGetFunction<F>::BindFunc(luaState, m_func);
            lua_settable(luaState, -3);
        }

        Registration::Register(luaState, bGlobal);
    }
};

#endif